package cn.pconline.autoclub.service;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;

import org.gelivable.dao.GeliDao;
import org.gelivable.dao.GeliOrm;
import org.gelivable.dao.Mid;
import org.gelivable.dao.SqlBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;

import cn.pconline.autoclub.entity.Photo;
import cn.pconline.autoclub.entity.PhotoPraise;
import cn.pconline.autoclub.entity.PhotoUserPraise;
import cn.pconline.autoclub.entity.User;
import cn.pconline.autoclub.util.Pager;

/**
 * @author zhouruxuan
 * @date 2015年2月28日 上午10:39:28
 */
public class PhotoPraiseService {

	@Autowired
    private GeliOrm geliOrm;
    @Autowired
    private GeliDao geliDao;
    @Autowired
    private JdbcTemplate jdbcTemplate;
    @Autowired
    private PagerService pagerService;
    @Autowired
    private AlbumService albumService;
    
    @Autowired
    private BaseService baseService;
    
    private static final Logger log = LoggerFactory.getLogger(PhotoPraiseService.class);
    
    /**
     * 获取某个赞信息
     * @param userId
     * @param photoId
     * @return
     */
    public PhotoPraise findPhotoPraiseById(long userId, long photoId) {
        try {
            return geliDao.find(PhotoPraise.class, photoId, new Mid(userId, photoId));
        } catch (EmptyResultDataAccessException e) {
            return null;
        }
    }
    
    /**
     * 获取某个赞信息
     * @param userId
     * @param photoId
     * @return
     */
    public PhotoUserPraise findPhotoUserPraiseById(long userId, long photoId, long photoCreateBy) {
        try {
            return geliDao.find(PhotoUserPraise.class, photoCreateBy, new Mid(userId, photoId));
        } catch (EmptyResultDataAccessException e) {
            return null;
        }
    }
    
    /**
     * 点赞/取消点赞
     * @param userId
     * @param photoId
     * @param albumId
     * @param status
     * @return
     */
    
    public boolean doPraise(long userId, long photoId, long albumId, int status) {
        Photo photo = albumService.getPhotoById(photoId, albumId);
        if (photo == null) {
            return false;
        }
        PhotoPraise photoPraise = findPhotoPraiseById(userId, photoId);
        if (photoPraise == null) {
            if (status == PhotoPraise.STATUS_UNPRAISE) {//没记录不能取消赞
                return false;
            }
            PhotoPraise pp = new PhotoPraise();
            pp.setPhotoCreateBy(photo.getCreateBy());
            pp.setPhotoId(photo.getPhotoId());
            pp.setAlbumId(photo.getAlbumId());
            
            //动态用户给自己点赞，标志为已读
            if (photo.getCreateBy() != userId) {
                pp.setIsRead(PhotoPraise.READ_NO);
            } else {
                pp.setIsRead(PhotoPraise.READ_YES);
            }
            pp.setPraiseTime(new Date());
            pp.setStatus(PhotoPraise.STATUS_PRAISE);//点赞
            pp.setUserId(userId);
            geliDao.create(pp);
            createPhotoUserPraise(pp);
            //点赞 计数+1
            increasePraiseCount(photo.getPhotoId(), photo.getAlbumId());
            return true;
        } else {
            if (photoPraise.getStatus() == status) {//状态没变化不操作
                return true;
            }
            if (status == PhotoPraise.STATUS_UNPRAISE) {//取消赞
                decreasePraiseCount(photo.getPhotoId(), photo.getAlbumId());
            } else {//点赞
                increasePraiseCount(photo.getPhotoId(), photo.getAlbumId());
            }
            photoPraise.setStatus(status);
            photoPraise.setPraiseTime(new Date());
            
            PhotoUserPraise photoUserPraise = findPhotoUserPraiseById(userId, photoId, photo.getCreateBy());
            if(photoUserPraise == null) {
                createPhotoUserPraise(photoPraise);
            }
            photoUserPraise.setStatus(photoPraise.getStatus());
            photoUserPraise.setPraiseTime(photoPraise.getPraiseTime());
            
            return geliDao.update(photoPraise, "status,praise_at") > 0;
        }
    }
    
    /**
     * 照片赞数+1
     * @param photoId
     * @param albumId
     */
    private void increasePraiseCount(long photoId, long albumId) {
        StringBuilder sql = new StringBuilder();
        sql.append("update ").append(geliOrm.getTableName(Photo.class, albumId));
        sql.append(" set praise_count = praise_count + 1 ");
        sql.append(" where photo_id = ").append(photoId);
        geliDao.getJdbcTemplate().update(sql.toString());
        geliDao.deleteCache(GeliDao.getCacheKey(Photo.class, photoId));
    }
    
    /**
     * 照片赞数-1
     * @param photoId
     * @param albumId
     */
    private void decreasePraiseCount(long photoId, long albumId) {
        StringBuilder sql = new StringBuilder();
        sql.append("update ").append(geliOrm.getTableName(Photo.class, albumId));
        sql.append(" set praise_count = praise_count - 1 ");
        sql.append(" where photo_id = ").append(photoId);
        geliDao.getJdbcTemplate().update(sql.toString());
        geliDao.deleteCache(GeliDao.getCacheKey(Photo.class, photoId));
    }
    
    /**
     * 收到的赞列表(不包括自赞的）
     * @param photoCreateBy
     * @param pageNo
     * @param pageSize
     * @return
     */
    public Pager<PhotoPraise> getPraiseList(long photoCreateBy, long photoId, int pageNo, int pageSize) {
        SqlBuilder sql = new SqlBuilder();
        sql.appendSql("select user_id,photo_id from ").appendSql(geliDao.getTableName(PhotoPraise.class, photoId));
        sql.appendSql(" where photo_create_by = ").appendValue(photoCreateBy);
        sql.appendSql(" and user_id <> ").appendValue(photoCreateBy);
        sql.appendSql(" order by praise_at desc");
        return pagerService.pager(PhotoPraise.class, sql, pageNo, pageSize);
    }
    
    /**
     * 未读点赞清零，返回操作成功的ID
     * @param photoCreateBy
     * @param photoIds
     * @return
     */
    public List<Long> clearUnreadPraise(long photoCreateBy, List<Long> photoIds) {
        List<Long> rs = new ArrayList<Long>();

        SqlBuilder sql = new SqlBuilder();
        sql.appendSql("select user_id,photo_id from ").appendSql(geliDao.getTableName(PhotoUserPraise.class, photoCreateBy));
        sql.appendSql(" where photo_create_by = ").appendValue(photoCreateBy);
        if (!photoIds.isEmpty()) {
            sql.appendSql(" and photo_id in ").appendValues(photoIds.toArray());
        }
        sql.appendSql(" and is_read = ").appendValue(PhotoPraise.READ_NO);
        sql.appendSql(" and status = ").appendValue(PhotoPraise.STATUS_PRAISE);
        try {
            List<PhotoUserPraise> list = geliDao.list(PhotoUserPraise.class, photoCreateBy, sql.getSql(), sql.getValues());
            for (PhotoUserPraise pup : list) {
                //修改ac_photo_user_praise_xx表
                pup = geliDao.find(PhotoUserPraise.class, photoCreateBy, new Mid(pup.getUserId(), pup.getPhotoId()));
                if(pup == null) {
                	continue;
                }
                if (pup.getIsRead() == PhotoUserPraise.READ_YES) {
                    rs.add(pup.getPhotoId());
                    continue;
                }
                pup.setIsRead(PhotoUserPraise.READ_YES);
                if (geliDao.update(pup, "is_read") > 0) {
                    rs.add(pup.getPhotoId());
                }
                
                //修改ac_photo_praise_xx表
                PhotoPraise pp = geliDao.find(PhotoPraise.class, pup.getPhotoId(), new Mid(pup.getUserId(), pup.getPhotoId()));
                if(pp == null) {
                	continue;
                }
                if (pp.getIsRead() == PhotoPraise.READ_YES) {
                    rs.add(pp.getPhotoId());
                    continue;
                }
                pp.setIsRead(PhotoPraise.READ_YES);
                if (geliDao.update(pp, "is_read") > 0) {
                    rs.add(pp.getPhotoId());
                }
            }
        } catch (EmptyResultDataAccessException e) {
            log.error("clearUnreadPraise error.", e);
        }
    
        return rs;
    }
    
    /**
     * 根据动态ID获取点赞的用户列表，按时间倒序排序
     * @param photoId
     * @param pageNo
     * @param pageSize
     * @return
     */
    public Pager<User> getPraiseUserList(long photoId, int pageNo, int pageSize) {
        SqlBuilder sql = new SqlBuilder();
        sql.appendSql("select user_id from ").appendSql(geliDao.getTableName(PhotoPraise.class, photoId));
        sql.appendSql(" where photo_id = ").appendValue(photoId);
        sql.appendSql(" and status = ").appendValue(PhotoPraise.STATUS_PRAISE);
        sql.appendSql(" order by praise_at desc");
        return pagerService.pager(User.class, sql, pageNo, pageSize);
    }

    /**
     * 用于判断是否已赞
     *
     * @param userId
     * @param photoIds
     * @return
     */
    public List<PhotoPraise> getPraiseList(long userId, List<Long> photoIds) {
        List<PhotoPraise> praises = new ArrayList<PhotoPraise>();
        for(Long photoId : photoIds) {
            PhotoPraise praise = findPhotoPraiseById(userId, photoId);
            if(praise != null && praise.getStatus() == PhotoPraise.STATUS_PRAISE) {
               praises.add(praise); 
            }
        }
        return praises;
    }
    
    /**
     * 判断用户是否已赞（单个图片）
     * @param userId
     * @param photoId
     * @return
     */
    public PhotoPraise getPhotoPraise(long userId,long photoId){
    	PhotoPraise praise = findPhotoPraiseById(userId, photoId);
    	if(praise!=null &&praise.getStatus()==PhotoPraise.STATUS_PRAISE){
    		return praise;
    	}
    	return null;
    }

    /**
     * 未读已赞数
     *
     * @param photoIdCreateBy
     * @return
     */
    public int getUnReadCount(long photoIdCreateBy) {
        SqlBuilder sql = new SqlBuilder();
        sql.appendSql("select count(1) from ").appendSql(geliDao.getTableName(PhotoUserPraise.class, photoIdCreateBy));
        sql.appendSql(" where photo_create_by = ").appendValue(photoIdCreateBy);
        sql.appendSql(" and user_id <> ").appendValue(photoIdCreateBy);
        sql.appendSql(" and status = ").appendValue(PhotoPraise.STATUS_PRAISE);
        sql.appendSql(" and is_read = ").appendValue(PhotoPraise.READ_NO);
        return geliDao.count(sql.getSql(), sql.getValues());
    }

    /**
     * 收到未读赞列表
     *
     * @param photoIdCreateBy
     * @return
     */
    public List<PhotoPraise> getUnReadList(long photoIdCreateBy) {
        SqlBuilder sql = new SqlBuilder();
        sql.appendSql("select user_id,photo_id ").appendSql(geliDao.getTableName(PhotoUserPraise.class, photoIdCreateBy));
        sql.appendSql(" where photo_create_by = ").appendValue(photoIdCreateBy);
        sql.appendSql(" and status = ").appendValue(PhotoPraise.STATUS_PRAISE);
        sql.appendSql(" and user_id <> ").appendValue(photoIdCreateBy);
        sql.appendSql(" and is_read = ").appendValue(PhotoPraise.READ_NO);
        sql.appendSql(" order by praise_at desc");
        try {
            return geliDao.list(PhotoPraise.class, sql.getSql(), sql.getValues());
        } catch (EmptyResultDataAccessException exception) {
            return Collections.emptyList();
        }
    }
    
    public PhotoPraise getLatestUnReadPraise(long photoIdCreateBy) {
        SqlBuilder sql = new SqlBuilder();
        sql.appendSql("select user_id,photo_id ").appendSql(geliDao.getTableName(PhotoUserPraise.class, photoIdCreateBy));
        sql.appendSql(" where photo_create_by = ").appendValue(photoIdCreateBy);
        sql.appendSql(" and status = ").appendValue(PhotoPraise.STATUS_PRAISE);
        sql.appendSql(" and user_id <> ").appendValue(photoIdCreateBy);
        sql.appendSql(" and is_read = ").appendValue(PhotoPraise.READ_NO);
        sql.appendSql(" order by praise_at desc");
        try {
            List<PhotoPraise> praise = geliDao.page(PhotoPraise.class, photoIdCreateBy, sql.getSql(), 1, 1, sql.getValues());
            if(praise != null && !praise.isEmpty()) {
                return praise.get(0);
            }
        } catch (EmptyResultDataAccessException e) {
            log.warn("user not unread paise");
        }
        return null;
    }
    
    public PhotoUserPraise getLatestPraise(long photoIdCreateBy) {
        SqlBuilder sql = new SqlBuilder();
        sql.appendSql("select user_id,photo_id from ").appendSql(geliDao.getTableName(PhotoUserPraise.class, photoIdCreateBy));
        sql.appendSql(" where photo_create_by = ").appendValue(photoIdCreateBy);
        sql.appendSql(" and status = ").appendValue(PhotoPraise.STATUS_PRAISE);
        sql.appendSql(" and user_id <> ").appendValue(photoIdCreateBy);
        sql.appendSql(" order by praise_at desc");
        try {
            List<PhotoUserPraise> praise = geliDao.page(PhotoUserPraise.class, photoIdCreateBy, sql.getSql(), 1, 1, sql.getValues());
            if(praise != null && !praise.isEmpty()) {
                return praise.get(0);
            }
        } catch (EmptyResultDataAccessException e) {
            log.warn("user not receive paise");
        }
        return null;
    }
    
    /**
     * 查询用户的相片被点赞列表
     */
    public Pager<PhotoUserPraise> getPraiseList(long photoIdCreateBy, int pageNo, int pageSize) {
        SqlBuilder sql = new SqlBuilder();
        sql.appendSql("select user_id,photo_id from ").appendSql(geliDao.getTableName(PhotoUserPraise.class, photoIdCreateBy));
        sql.appendSql(" where photo_create_by = ").appendValue(photoIdCreateBy);
        sql.appendSql(" and status = ").appendValue(PhotoPraise.STATUS_PRAISE);
        sql.appendSql(" and user_id <> ").appendValue(photoIdCreateBy);
        sql.appendSql(" order by praise_at desc");
        return pagerService.pager(PhotoUserPraise.class, photoIdCreateBy, sql, pageNo, pageSize);
    }

    /**
     * 用户是否点赞过某个照片
     * @param photoId
     * @param userId
     * @return
     */
    public int getPraiseCountByUid(long photoId, long userId) {
        SqlBuilder sql = new SqlBuilder();
        sql.appendSql("select count(1) from ").appendSql(geliDao.getTableName(PhotoPraise.class, photoId));
        sql.appendSql(" where photo_id = ").appendValue(photoId);
        sql.appendSql(" and user_id =").appendValue(userId);
        sql.appendSql(" and status = ").appendValue(PhotoPraise.STATUS_PRAISE);
        return geliDao.count(sql.getSql(), sql.getValues());
    }
    
    private boolean createPhotoUserPraise(PhotoPraise photoPraise) {
        PhotoUserPraise photoUserPraise = new PhotoUserPraise(); 
        //= GeliDao.string2Object(PhotoUserPraise.class, JSON.toJSONString(photoPraise));
        photoUserPraise.setAlbumId(photoPraise.getAlbumId());
        photoUserPraise.setIsRead(photoPraise.getIsRead());
        photoUserPraise.setPhotoCreateBy(photoPraise.getPhotoCreateBy());
        photoUserPraise.setPhotoId(photoPraise.getPhotoId());
        photoUserPraise.setPraiseTime(photoPraise.getPraiseTime());
        photoUserPraise.setStatus(photoPraise.getStatus());
        photoUserPraise.setUserId(photoPraise.getUserId());
        return baseService.createDuplicateIgnore(photoUserPraise);
    }
}
